table of contents
perlrequick(1) | 2007-10-27-16:31 | perlrequick(1) |
Назва¶
perlrequick - ознайомлення з регулярними виразами Perl
Опис¶
Ця сторінка охоплює основи розуміння, створення і використання регулярних виразів ('рег. виразів') у Perl.
Простий збіг зі словами. ¶
Найпростіший регулярний вираз - це просто слово, або загальніше - ланцюжок знаків. Регулярний вираз, що складається зі слова збіжиться з будь-яким ланцюжком, що містить це слово:
"Hello World" =~ /World/; # зійдеться
Вирази на зразок цього корисні для перевірки умов:
print "It matches\n" if "Hello World" =~ /World/;
print "It doesn't match\n" if "Hello World" !~ /World/;
$greeting = "World";
print "It matches\n" if "Hello World" =~ /$greeting/;
$_ = "Hello World";
print "It matches\n" if /World/;
print "It matches\n" if /World/;
"Hello World" =~ m!World!; # обмежувач '!'
"Hello World" =~ m{World}; # парні обмежувачі '{}'
"/usr/bin/perl" =~ m"/perl"; # лапки як обмежувач,
# '/' в ролі звичайного знаку
"Hello World" =~ /world/; # не сходиться за регістром
"Hello World" =~ /o W/; # зійдеться, ' ' є звичайним символом
"Hello World" =~ /World /; # не зійдеться, немає ' ' наприкінці
"Hello World" =~ /o/; # збіглося з 'o' в 'Hello'
"That hat is red" =~ /hat/; # зійшлося з 'hat' з 'That'
{}[]()^$.|*+?\
"2+2=4" =~ /2+2/; # не збігається, + є метазнаком
"2+2=4" =~ /2\+2/; # зійдеться, \+ розглядається як
# звичний +
'C:\WIN32' =~ /C:\\WIN/; # зійдеться
"/usr/bin/perl" =~ /\/usr\/bin\/perl/; # зійдеться
Недруковні символи ASCII представлені керівними послідовностями. Спільними прикладами є "\t", що позначає табуляцію, "\n" - знак нового рядка, "\r" - повернення каретки тощо. Довільні байти можна представити вісімковими керівними послідовностями, наприклад "\033", або шістнадцятковими, як от "\x1B":
"1000\t2000" =~ m(0\t2) # зійдеться
"cat" =~ /\143\x61\x74/ # зійдеться, хоч це й дивний спосіб
# написання слова "cat" (кішка)
$foo = 'house';
'cathouse' =~ /cat$foo/; # зійдеться
'housecat' =~ /${foo}cat/; # зійдеться
"housekeeper" =~ /keeper/; # зійдеться
"housekeeper" =~ /^keeper/; # не зійдеться
"housekeeper" =~ /keeper$/; # сходиться
"housekeeper\n" =~ /keeper$/; # сходиться
"housekeeper" =~ /^housekeeper$/; # сходиться
Класи знаків ¶
Клас знаків дозволяє вказати набір можливих знаків, а не тільки один. Класи вказуються за допомогою квадратних дужок "[...]" із набором імовірних знаків. Ось декілька прикладів:
/cat/; # зійдеться з 'cat'
/[bcr]at/; # зійдеться з 'bat', 'cat' або 'rat'
"abc" =~ /[cab]/; # зійдеться через 'a'
/[yY][eE][sS]/; # зіставити з 'yes' у регістро-незалежний спосіб
# 'yes', 'Yes', 'YES' тощо
/yes/i; # так само зіставити з 'yes', не залежачи від
# регістру
Класи знаків так само включають звичайні знаки і спеціальні, але зміст набору спеціальних знаків усередині класу відрізняється від того, що використовуються ззовні. Спеціальними для класу вважаються "-]\^$" і буквального співпадання можна добитися за допомогою зворотнього слешу:
/[\]c]def/; # збігається з ']def' or 'cdef'
$x = 'bcr';
/[$x]at/; # збігається з 'bat, 'cat' і 'rat'
/[\$x]at/; # зійдеться з '$at' і 'xat'
/[\\$x]at/; # зійдеться з '\at', 'bat, 'cat' і 'rat'
/item[0-9]/; # збігається з 'item0' аж до 'item9'
/[0-9a-fA-F]/; # зійдеться з шістнадцятковим числом
Спеціальний знак "^", якщо стоїть першим усередині класу, позначає заперечення цього класу знаків, що призведе до збігу з будь-яким знаком *за винятком* тих, що включено в квадратні дужки. Обидва, "[...]" і "[^...]", повинні зійтися з якимось символом, інакше порівняння зазнає невдачі. Таким чином,
/[^a]at/; # не зійдеться з 'aat' або 'at', зате
# із рештою, як от 'bat', 'cat, '0at', '%at' тощо.
/[^0-9]/; # зійдеться із нечисловим символом
/[a^]at/; # зійдеться з 'aat' або '^at'; тут '^' звичайний
- \d
-
позначає цифру, тотожно [0-9] - \s
-
позначає пробіл, тотожно [\ \t\r\n\f] - \w
-
позначає символ, який може бути частиною слова (алфавітно-числовий або _), тотожно [0-9a-zA-Z_] - \D
-
протилежний \d; будь-який символ окрім цифри, тотожно [^0-9] - \S
-
протилежний \s; будь-який символ окрім пробілу, тотожно [^\s] - \W
-
протилежний \w; будь-який символ окрім тих, що можуть складати слово, [^\w] - \&.
-
(крапка) збігається з будь-яким знаком окрім \nСкорочення "\d\s\w\D\S\W" можна вживати всередині і поза межами класу знаків. Ось декілька прикладів використання:
/\d\d:\d\d:\d\d/; # збігається з форматом часу гг:хх:сс
/[\d\s]/; # збігається з будь-якою цифрою або пробілом
/\w\W\w/; # збігається зі знаком, що складатиме слово
# із наступним знаком, що не є частиною слова із
# наступним знаком слова
/..rt/; # збігається з будь-якими двома знаками і 'rt'
/end\./; # збігається з 'end.'
/end[.]/; # те саме, збігається з 'end.'
$x = "Housecat catenates house and cat";
$x =~ /\bcat/; # збігається з cat у 'catenates'
$x =~ /cat\b/; # збігається з cat у 'housecat'
$x =~ /\bcat\b/; # збігається з 'cat' наприкінці ланцюжка
Порівнювання з тим або іншим ¶
Ми можемо порівняти з різноманітними символьними ланцюжками за допомогою метасимволу альтернативи '|'. Щоб збіглося із "dog" або "cat", ми створимо рег. вираз "dog|cat". Як і раніше, Perl намагатиметься знайти збіг у найпершому можливому місці ланцюжка. В кожній позиції perl спочатку пробує зіставити з першою альтернативою "dog". Якщо "dog" не співпав, perl спробує тоді другу альтернативу "cat". Якщо "cat" також не збігається, тоді перевірка зазнає невдачі і perl переходить до наступної позиції в ланцюжкові. Декілька прикладів:
"cats and dogs" =~ /cat|dog|bird/; # збігається з "cat"
"cats and dogs" =~ /dog|cat|bird/; # збігається з "cat"
"cats" =~ /c|ca|cat|cats/; # збігається з "c"
"cats" =~ /cats|cat|ca|c/; # збігається з "cats"
Групування речей і ієрархічне порівнювання ¶
Метасимвол групування "()" дозволяє розглянути частину регулярного виразу як єдине ціле. Окремі частини рег. виразу згруповано шляхом включення їх у круглі дужки. Регулярний вираз "house(cat|keeper)" означає збіг із "house" із наступним або "cat", або "keeper". Ще декілька прикладів:
/(a|b)b/; # збігається з 'ab' або 'bb'
/(^a|b)c/; # збігається 'ac' на початку ланцюжка і 'bc' деінде
/house(cat|)/; # збігається з або 'housecat', або 'house'
/house(cat(s|)|)/; # збігається з або 'housecats', або 'housecat',
# або 'house'. Зверніть увагу, що групи можуть
# гніздитися
"20" =~ /(19|20|)\d\d/; # збігається з нульовою альтернативою
# '()\d\d', оскільки '20\d\d' не співпадає
Звертання до збігів ¶
Метасимвол групування "()" також дозволяє здобуття частин ланцюжка, що зійшлися. Для кожної групи, частину, що збіглася, буде збережено в спеціальні змінні $1, $2 і.т.д. Їх можна застосовувати як звичайні змінні:
# добути години, хвилини, секунди
$time =~ /(\d\d):(\d\d):(\d\d)/; # збігається з форматом гг:хх:сс
$hours = $1;
$minutes = $2;
$seconds = $3
($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/);
/(ab(cd|ef)((gi)|j))/;
1 2 34
/(\w\w\w)\s\1/; # знайти послідовності на кшталт 'the the'
# в ланцюжкові
Повторення збігів ¶
Метасимволи-квантори (кількісні метасимволи) "?", "*", "+" і "{}" дозволяють нам визначити число повторень частини регулярного виразу, який ми вважаємо, що збігся. Квантори додаються одразу після знаку, класу знаків або групи, які ми вказали. Вони означають наступне:
- a?
-
збігтися з 'a' 1 або 0 разів - a*
-
збігтися з 'а' 0 або більше разів, тобто будь-яку кількість разів - a+
-
збігтися з 'a' 1 або більше разів, тобто щонайменше один раз - a{n,m}
-
збігтися щонайменше "n" раз, але не більше ніж "m" раз - a{n,}
-
збігтися щонайменше "n" або більше разів - a{n}
-
збігтися точно "n" разЗ наступними прикладами:
/[a-z]+\s+\d*/; # зійдеться зі словом у нижньому регістрі,
# принаймні одним пробілом, і будь-якою кількістю
# цифр
/(\w+)\s+\1/; # зійдеться з повтореним словом довільної довжини
$year =~ /\d{2,4}/; # впевнитись, що $year складається з
# щонайменше 2 цифр, але не більше за 4
$year =~ /\d{4}|\d{2}/; # навіть краще; відкидає дати з 3-ох цифр
$x = 'the cat in the hat';
$x =~ /^(.*)(at)(.*)$/; # зійдуться
# $1 = 'the cat in the h'
# $2 = 'at'
# $3 = '' (0 співпадань)
Інші порівняння ¶
Існує ще декілька речей, які вам цікаво би було знати про оператори збігів.
Маючи код
$pattern = 'Seuss';
while (<>) {
print if /$pattern/;
}
@pattern = ('Seuss');
m/@pattern/; # збігається з 'Seuss'
m'@pattern'; # збігається з буквальним ланцюжком '@pattern'
$x = "cat dog house"; # 3 words
while ($x =~ /(\w+)/g) {
print "Word is $1, ends at position ", pos $x, "\n";
}
Word is cat, ends at position 3
Word is dog, ends at position 7
Word is house, ends at position 13
В контексті списку, "//g" повертає список груп, що співпали, або якщо групування відсутнє - список збігів із цілим регулярним виразом. Тож
@words = ($x =~ /(\w+)/g); # збігається,
# $word[0] = 'cat'
# $word[1] = 'dog'
# $word[2] = 'house'
Пошук і заміна ¶
Пошук із заміною відбувається за схемою "s/рег. вираз/текст заміни/модифікатори". Текст заміни змістить те, що співпало з рег. виразом в ланцюжку. Оператор "=~" також застосовується тут для того, щоб пов'язати ланцюжок із дією "s///". Якщо порівнюється супроти $_, то вираз "$_ =~" можна опустити. При вдалім порівнянні, "s///" повертає число здійснених замін, у протилежному випадку - хибно. Ось деякі приклади:
$x = "Time to feed the cat!";
$x =~ s/cat/hacker/; # $x міститиме "Time to feed the hacker!"
$y = "'quoted words'";
$y =~ s/^'(.*)'$/$1/; # видалити одинарні лапки,
# $y міститиме "quoted words"
$x = "I batted 4 for 4";
$x =~ s/4/four/; # $x міститиме "I batted four for 4"
$x = "I batted 4 for 4";
$x =~ s/4/four/g; # $x міститиме "I batted four for four"
# обернути всі слова в ланцюжку
$x = "the cat in the hat";
$x =~ s/(\w+)/reverse $1/ge; # $x міститиме "eht tac ni eht tah"
# перетворити відсотки на десяткові числа
$x = "A 39% hit rate";
$x =~ s!(\d+)%!$1/100!e; # $x міститиме "A 0.39 hit rate"
Оператор split ¶
"split /рег. вираз/, ланцюжок" розбиває ланцюжок на список з його частин і повертає цей список. Регулярний вираз визначає послідовність знаків, згідно з яким відбувається розбиття. Так, скажімо, щоб розбити ланцюжок на слова використайте
$x = "Calvin and Hobbes";
@word = split /\s+/, $x; # $word[0] = 'Calvin'
# $word[1] = 'and'
# $word[2] = 'Hobbes'
$x = "1.618,2.718, 3.142";
@const = split /,\s*/, $x; # $const[0] = '1.618'
# $const[1] = '2.718'
# $const[2] = '3.142'
$x = "/usr/bin";
@parts = split m!(/)!, $x; # $parts[0] = ''
# $parts[1] = '/'
# $parts[2] = 'usr'
# $parts[3] = '/'
# $parts[4] = 'bin'
Вади¶
Жодних.
Дивіться також¶
Ця сторінка являється лише швидким введенням для початківців. Для глибшого ознайомлення з регулярними виразами зверніться до perlretut(1) і довідника perlre(1).
Переклав українською Віталій Цибуляк.
2007-10-27-16:31 | © 2005-2007 DLOU, GNU FDL |